classdef RandomKLabelsetsDisjoint < RandomKLabelsets
    %RANDOMKLABELSETSDISJOINT Random K Labelsets Disjoint (RAkEL_d)
    %   Detailed explanation goes here
    
    properties ( SetAccess = protected )
    end
    
    methods
        function [ this ] = RandomKLabelsetsDisjoint( name, ...
                nSubLabel, algorithm0 )
            if nargin == 0
                this.setName('rakel_d');
            end
            if nargin >= 1
                this.setName(name);
            end
            if nargin >= 2
                this.setNSubLabel(nSubLabel);
            end
            if nargin >= 3
                this.setAlgorithm0(algorithm0);
            end
        end
    end
    
    methods
        function [  ] = build( this, X1, Y1 )
            %BUILD Summary of this function goes here
            %   Detailed explanation goes here
            % RandomKLabelsetsDisjoint::build
            
            nLab = size(Y1, 2);
            this.zSubLabelset = generateZLabelset(this.randomSeed, nLab, this.nSubLabel);
            
            nLabelset = length(this.zSubLabelset);
            this.zAlgorithm = cell(1, nLabelset);
            
            for iLabelset = 1:nLabelset
                zSubLabelId_i = this.zSubLabelset{iLabelset};
                
                this.zAlgorithm{iLabelset} = this.algorithm0.clone();
                this.zAlgorithm{iLabelset}.build(X1, Y1(:, zSubLabelId_i));
            end
        end
        
        function [ result2 ] = apply( this, X2, Y2 )
            %APPLY Summary of this function goes here
            %   Detailed explanation goes here
            % RandomKLabelsetsDisjoint::apply
            
            nLabelset = length(this.zSubLabelset);
            
            Y2_hat = nan(size(Y2));
            Y2_out = Y2_hat;
            
            for iLabelset = 1:nLabelset
                zSubLabelId_i = this.zSubLabelset{iLabelset};
                
                result2_i ...
                    = this.zAlgorithm{iLabelset}.apply(X2, Y2(:, zSubLabelId_i));
                
                Y2_hat(:, zSubLabelId_i) = result2_i.Y_hat;
                Y2_out(:, zSubLabelId_i) = result2_i.Y_out;
            end
            
            result2.Y_hat = Y2_hat;
            result2.Y_out = Y2_out;
        end
    end
    
end

function [ zLabelset ] = generateZLabelset( randomSeed, nLab, nSubLabel )

rng(randomSeed);

zLab = 1:nLab;
nLabelset = ceil(nLab/nSubLabel);
zLabelset =  cell(1, nLabelset);

for iLabelset = 1:nLabelset
    for jSubLabel = 1:nSubLabel
        if ~isempty(zLab)
            ijLab = randi(length(zLab));
            zLabelset{iLabelset}(jSubLabel) = zLab(ijLab);
            zLab(ijLab) = [];
        else
            break
        end
    end
end

end
